using Microsoft.Phone.Controls.Maps.AutomationPeers;
using Microsoft.Phone.Controls.Maps.Core;
using System;
using System.Collections.Generic;
using System.Device.Location;
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Controls;
using System.Windows.Media;
namespace Microsoft.Phone.Controls.Maps
{
	public sealed class MapLayer : MapLayerBase, IProjectable
	{
		private Guid lastProjectPassTag;
		private ProjectionUpdateLevel pendingUpdate = ProjectionUpdateLevel.Full;
		public static readonly DependencyProperty PositionProperty = DependencyProperty.RegisterAttached("Position", typeof(GeoCoordinate), typeof(MapLayer), new PropertyMetadata(new PropertyChangedCallback(MapLayer.OnPositionChanged)));
		public static readonly DependencyProperty PositionRectangleProperty = DependencyProperty.RegisterAttached("PositionRectangle", typeof(LocationRect), typeof(MapLayer), new PropertyMetadata(new PropertyChangedCallback(MapLayer.OnPositionRectangleChanged)));
		public static readonly DependencyProperty PositionOriginProperty = DependencyProperty.RegisterAttached("PositionOrigin", typeof(PositionOrigin), typeof(MapLayer), new PropertyMetadata(new PropertyChangedCallback(MapLayer.OnPositionOriginChanged)));
		public static readonly DependencyProperty PositionOffsetProperty = DependencyProperty.RegisterAttached("PositionOffset", typeof(Point), typeof(MapLayer), new PropertyMetadata(new PropertyChangedCallback(MapLayer.OnPositionOffsetChanged)));
		private static readonly DependencyProperty ProjectionUpdatedTag = DependencyProperty.RegisterAttached("ProjectionUpdatedTagProperty", typeof(Guid), typeof(MapLayer), null);
		public MapBase ParentMap
		{
			get
			{
				IProjectable projectable = base.get_Parent() as IProjectable;
				if (projectable != null)
				{
					return projectable.ParentMap;
				}
				MapBase mapBase = base.get_Parent() as MapBase;
				if (mapBase != null)
				{
					return mapBase;
				}
				ItemsPresenter itemsPresenter = VisualTreeHelper.GetParent(this) as ItemsPresenter;
				if (itemsPresenter != null)
				{
					IProjectable projectable2 = VisualTreeHelper.GetParent(itemsPresenter) as IProjectable;
					if (projectable2 != null)
					{
						return projectable2.ParentMap;
					}
				}
				return null;
			}
		}
		public override void AddChild(UIElement element, GeoCoordinate location)
		{
			base.get_Children().Add(element);
			element.SetValue(MapLayer.PositionProperty, location);
		}
		public override void AddChild(UIElement element, GeoCoordinate location, Point offset)
		{
			base.get_Children().Add(element);
			element.SetValue(MapLayer.PositionProperty, location);
			element.SetValue(MapLayer.PositionOffsetProperty, offset);
		}
		public override void AddChild(UIElement element, GeoCoordinate location, PositionOrigin origin)
		{
			base.get_Children().Add(element);
			element.SetValue(MapLayer.PositionProperty, location);
			element.SetValue(MapLayer.PositionOriginProperty, origin);
		}
		public override void AddChild(UIElement element, LocationRect locationRect)
		{
			base.get_Children().Add(element);
			element.SetValue(MapLayer.PositionRectangleProperty, locationRect);
		}
		public static GeoCoordinate GetPosition(DependencyObject dependencyObject)
		{
			GeoCoordinate geoCoordinate = (GeoCoordinate)dependencyObject.GetValue(MapLayer.PositionProperty);
			if (geoCoordinate == null && dependencyObject is ContentPresenter && VisualTreeHelper.GetChildrenCount(dependencyObject) > 0)
			{
				DependencyObject child = VisualTreeHelper.GetChild(dependencyObject, 0);
				if (child != null)
				{
					geoCoordinate = MapLayer.GetPosition(child);
				}
			}
			return geoCoordinate;
		}
		public static void SetPosition(DependencyObject dependencyObject, GeoCoordinate position)
		{
			dependencyObject.SetValue(MapLayer.PositionProperty, position);
		}
		private static void OnPositionChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs ea)
		{
			MapLayer.InvalidateParentLayout(dependencyObject);
		}
		public static LocationRect GetPositionRectangle(DependencyObject dependencyObject)
		{
			LocationRect locationRect = (LocationRect)dependencyObject.GetValue(MapLayer.PositionRectangleProperty);
			if (locationRect == null && dependencyObject is ContentPresenter && VisualTreeHelper.GetChildrenCount(dependencyObject) > 0)
			{
				DependencyObject child = VisualTreeHelper.GetChild(dependencyObject, 0);
				if (child != null)
				{
					locationRect = MapLayer.GetPositionRectangle(child);
				}
			}
			return locationRect;
		}
		public static void SetPositionRectangle(DependencyObject dependencyObject, LocationRect rect)
		{
			dependencyObject.SetValue(MapLayer.PositionRectangleProperty, rect);
		}
		private static void OnPositionRectangleChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs ea)
		{
			MapLayer.InvalidateParentLayout(dependencyObject);
		}
		public static PositionOrigin GetPositionOrigin(DependencyObject dependencyObject)
		{
			PositionOrigin result = (PositionOrigin)dependencyObject.GetValue(MapLayer.PositionOriginProperty);
			if (dependencyObject is ContentPresenter && VisualTreeHelper.GetChildrenCount(dependencyObject) > 0)
			{
				DependencyObject child = VisualTreeHelper.GetChild(dependencyObject, 0);
				if (child != null)
				{
					result = MapLayer.GetPositionOrigin(child);
				}
			}
			return result;
		}
		public static void SetPositionOrigin(DependencyObject dependencyObject, PositionOrigin origin)
		{
			dependencyObject.SetValue(MapLayer.PositionOriginProperty, origin);
		}
		private static void OnPositionOriginChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs ea)
		{
			MapLayer.InvalidateParentLayout(dependencyObject);
		}
		public static Point GetPositionOffset(DependencyObject dependencyObject)
		{
			Point result = (Point)dependencyObject.GetValue(MapLayer.PositionOffsetProperty);
			if (dependencyObject is ContentPresenter && VisualTreeHelper.GetChildrenCount(dependencyObject) > 0)
			{
				DependencyObject child = VisualTreeHelper.GetChild(dependencyObject, 0);
				if (child != null)
				{
					result = MapLayer.GetPositionOffset(child);
				}
			}
			return result;
		}
		public static void SetPositionOffset(DependencyObject dependencyObject, Point point)
		{
			dependencyObject.SetValue(MapLayer.PositionOffsetProperty, point);
		}
		private static void OnPositionOffsetChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs ea)
		{
			MapLayer.InvalidateParentLayout(dependencyObject);
		}
		public void ProjectionUpdated(ProjectionUpdateLevel updateLevel)
		{
			if (updateLevel != ProjectionUpdateLevel.None)
			{
				base.InvalidateArrange();
				base.InvalidateMeasure();
				this.pendingUpdate |= updateLevel;
			}
		}
		protected override Size MeasureOverride(Size availableSize)
		{
			MapBase parentMap = this.ParentMap;
			if (parentMap != null)
			{
				Guid guid = this.lastProjectPassTag;
				this.lastProjectPassTag = Guid.NewGuid();
				using (IEnumerator<UIElement> enumerator = base.get_Children().GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						UIElement current = enumerator.get_Current();
						IProjectable projectable = current as IProjectable;
						if (projectable != null)
						{
							ProjectionUpdateLevel projectionUpdateLevel = this.pendingUpdate;
							if ((Guid)current.GetValue(MapLayer.ProjectionUpdatedTag) != guid)
							{
								projectionUpdateLevel = ProjectionUpdateLevel.Full;
							}
							if (projectionUpdateLevel != ProjectionUpdateLevel.None)
							{
								projectable.ProjectionUpdated(projectionUpdateLevel);
							}
							current.SetValue(MapLayer.ProjectionUpdatedTag, this.lastProjectPassTag);
						}
					}
				}
				this.pendingUpdate = ProjectionUpdateLevel.None;
				using (IEnumerator<UIElement> enumerator2 = base.get_Children().GetEnumerator())
				{
					while (enumerator2.MoveNext())
					{
						UIElement current2 = enumerator2.get_Current();
						LocationRect positionRectangle = MapLayer.GetPositionRectangle(current2);
						if (positionRectangle != null)
						{
							Rect rect = parentMap.Mode.LocationToViewportPoint(positionRectangle);
							current2.Measure(new Size(rect.get_Width(), rect.get_Height()));
						}
						else
						{
							if (current2 is ContentPresenter && VisualTreeHelper.GetChildrenCount(current2) > 0)
							{
								IProjectable projectable2 = VisualTreeHelper.GetChild(current2, 0) as IProjectable;
								if (projectable2 != null)
								{
									projectable2.ProjectionUpdated(ProjectionUpdateLevel.Full);
									UIElement uIElement = projectable2 as UIElement;
									if (uIElement != null)
									{
										uIElement.InvalidateMeasure();
									}
								}
							}
							current2.Measure(parentMap.ViewportSize);
						}
					}
				}
				return parentMap.ViewportSize;
			}
			return new Size(0.0, 0.0);
		}
		protected override Size ArrangeOverride(Size finalSize)
		{
			MapBase parentMap = this.ParentMap;
			if (parentMap != null)
			{
				using (IEnumerator<UIElement> enumerator = base.get_Children().GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						UIElement current = enumerator.get_Current();
						Rect rect = new Rect(0.0, 0.0, parentMap.ViewportSize.get_Width(), parentMap.ViewportSize.get_Height());
						LocationRect positionRectangle = MapLayer.GetPositionRectangle(current);
						if (positionRectangle != null)
						{
							rect = parentMap.Mode.LocationToViewportPoint(positionRectangle);
						}
						else
						{
							GeoCoordinate position = MapLayer.GetPosition(current);
							Point point;
							if (position != null && parentMap.TryLocationToViewportPoint(position, out point))
							{
								PositionOrigin positionOrigin = MapLayer.GetPositionOrigin(current);
								point.set_X(point.get_X() - positionOrigin.X * current.get_DesiredSize().get_Width());
								point.set_Y(point.get_Y() - positionOrigin.Y * current.get_DesiredSize().get_Height());
								if (Math.Abs(point.get_X()) > 100000.0)
								{
									point.set_X((double)(Math.Sign(point.get_X()) * 100000));
								}
								if (Math.Abs(point.get_Y()) > 100000.0)
								{
									point.set_Y((double)(Math.Sign(point.get_Y()) * 100000));
								}
								rect = new Rect(point.get_X(), point.get_Y(), current.get_DesiredSize().get_Width(), current.get_DesiredSize().get_Height());
							}
						}
						Point positionOffset = MapLayer.GetPositionOffset(current);
						rect.set_X(rect.get_X() + positionOffset.get_X());
						rect.set_Y(rect.get_Y() + positionOffset.get_Y());
						current.Arrange(rect);
					}
				}
			}
			if (parentMap == null)
			{
				return new Size(0.0, 0.0);
			}
			return parentMap.ViewportSize;
		}
		private static void InvalidateParentLayout(DependencyObject dependencyObject)
		{
			FrameworkElement frameworkElement = dependencyObject as FrameworkElement;
			if (frameworkElement != null)
			{
				MapLayer mapLayer = frameworkElement.get_Parent() as MapLayer;
				if (mapLayer == null)
				{
					ContentPresenter contentPresenter = frameworkElement.get_Parent() as ContentPresenter;
					if (contentPresenter != null)
					{
						mapLayer = (contentPresenter.get_Parent() as MapLayer);
					}
				}
				if (mapLayer != null)
				{
					mapLayer.InvalidateMeasure();
					mapLayer.InvalidateArrange();
				}
			}
		}
		protected override AutomationPeer OnCreateAutomationPeer()
		{
			return new BaseAutomationPeer(this, "MapLayer");
		}
	}
}
